﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace SmartMathLibrary
{
    /// <summary>
    /// This class provides the constructing of a polynomial out of it´s roots and one point.
    /// </summary>
    [Serializable]
    public class PolynomialConstructor
    {
        /// <summary>
        /// The roots of the polynomial to construct.
        /// </summary>
        private GeneralVector roots;

        /// <summary>
        /// One point of the polynomial, which is no root.
        /// </summary>
        private Point2D polynomialPoint;

        /// <summary>
        /// The roots of the polynomial to construct.
        /// </summary>
        public GeneralVector Roots
        {
            get { return roots; }
            set { roots = value; }
        }

        /// <summary>
        /// One point of the polynomial, which is no root.
        /// </summary>
        public Point2D PolynomialPoint
        {
            get { return polynomialPoint; }
            set { polynomialPoint = value; }
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="PolynomialConstructor"/> class.
        /// </summary>
        /// <param name="roots">The roots of the polynomial to construct.</param>
        /// <param name="polynomialPoint">One point of the polynomial, which is no root.</param>
        public PolynomialConstructor(GeneralVector roots, Point2D polynomialPoint)
        {
            if (roots.Count == 1)
            {
                throw new ArgumentException("To construct a polynomial a minimum of two roots are required.");
            }

            this.roots = roots;
            this.polynomialPoint = polynomialPoint;
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="PolynomialConstructor"/> class.
        /// </summary>
        /// <param name="roots">The roots of the polynomial to construct.</param>
        /// <param name="polynomialPoint">One point of the polynomial, which is no root.</param>
        public PolynomialConstructor(double[] roots, Point2D polynomialPoint)
        {
            if (polynomialPoint == (Point2D) null)
            {
                throw new ArgumentNullException("polynomialPoint");
            }

            if (roots.Length < 1)
            {
                throw new ArgumentException("roots.Length < 1", "roots");
            }

            if (roots.Length == 1)
            {
                throw new ArgumentException("To construct a polynomial a minimum of two roots are required.");
            }

            this.roots = new GeneralVector(roots);
            this.polynomialPoint = polynomialPoint;
        }

        /// <summary>
        /// Constructs the polynomial out of the specified data.
        /// </summary>
        /// <returns>The constructed polynomial.</returns>
        public SimplePolynomial ConstructPolynomial()
        {
            LinearFactorCollection linearFactorCollection = new LinearFactorCollection();

            for (int i = 0; i < this.roots.Count; i++)
            {
                linearFactorCollection.Add(new LinearFactor(-this.roots[i]));
            }

            SimplePolynomial result = linearFactorCollection.MultiplyFactors();

            result.MultiplyWithScalar(this.polynomialPoint.Y / (result.SolveAt(this.polynomialPoint.X)));

            return result;
        }
    }
}